package com.linkstec.base.util;

import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.PoolingClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;


public class HttpClientUtil {
    static PoolingClientConnectionManager poolingClientConnectionManager = new PoolingClientConnectionManager();
    static Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);

    static {
        poolingClientConnectionManager.setMaxTotal(200);
        poolingClientConnectionManager.setDefaultMaxPerRoute(20);
    }

    /**
     * post Json请求
     *
     * @param params 第三方接口的入参数据
     * @param url    第三方接口url
     * @return
     */
    public static String sendPost(String url, Map<String, Object> params) {
        DefaultHttpClient client = new DefaultHttpClient(poolingClientConnectionManager);
        setClientConnectionParams(client);
        HttpResponse response = null;
        logger.info("http调用url={}", url);
        try {
			URIBuilder uriBuilder = new URIBuilder(url);
			uriBuilder.addParameter("access_token", String.valueOf(params.get("access_token")));
			HttpPost httpPost = new HttpPost(uriBuilder.build());
            httpPost.addHeader("Content-type", "application/json;charset=utf-8");
            httpPost.addHeader("Accept", "application/json");
            logger.info("http调取出参params={}", JSONObject.toJSONString(params));
            StringEntity entity = new StringEntity(JSONObject.toJSONString(params), Charset.forName("UTF-8"));
            httpPost.setEntity(entity);
            response = client.execute(httpPost);
            if (response.getStatusLine().getStatusCode() != 200) {
                logger.error("http接口异常返回code={}", response.getStatusLine().getStatusCode());
                response.getEntity().getContent().close();
                return null;
            }
            String result = EntityUtils.toString(response.getEntity(), "UTF-8");
			return result;
        } catch (Exception e) {
            logger.error("HttpClient - sendPost(Map) 接口异常" + e.getMessage());
            e.printStackTrace();
        } finally {
            client.getConnectionManager().closeIdleConnections(1, TimeUnit.MINUTES);
        }
        return null;
    }

    public static String sendPost(String url, JSONObject jsonObject) {
        DefaultHttpClient client = new DefaultHttpClient(poolingClientConnectionManager);
        setClientConnectionParams(client);
        HttpResponse response = null;
        try {
			URIBuilder uriBuilder = new URIBuilder(url);
			uriBuilder.addParameter("access_token", jsonObject.getString("access_token"));
            HttpPost httpPost = new HttpPost(uriBuilder.build());
            httpPost.addHeader("Content-type", "application/json;charset=utf-8");
            httpPost.addHeader("Accept", "application/json");
            StringEntity entity = new StringEntity(jsonObject.toString(), Charset.forName("UTF-8"));
            logger.info("调用第三方接口入参：" + jsonObject.toString());
            httpPost.setEntity(entity);
            response = client.execute(httpPost);
            if (response.getStatusLine().getStatusCode() != 200) {
                response.getEntity().getContent().close();
                return null;
            }
            String result = EntityUtils.toString(response.getEntity(), "UTF-8");
            logger.info("第三方接口返回数据：" + result);
			return result;
        } catch (Exception e) {
            logger.error("HttpClient - sendPost(JSONObject) 接口异常" + e.getMessage());
            e.printStackTrace();
        } finally {
            client.getConnectionManager().closeIdleConnections(1, TimeUnit.MINUTES);
        }
        return null;
    }

    /**
     * post 表单请求
     *
     * @param url 传递给第三方接口的入参
     * @param map 第三方接口url
     * @return 返回第三方接口数据
     */
    public static String sendPostForm(String url, Map<String, Object> map) {
        DefaultHttpClient client = new DefaultHttpClient(poolingClientConnectionManager);
        setClientConnectionParams(client);
        HttpResponse response = null;
        try {
			URIBuilder uriBuilder = new URIBuilder(url);
			uriBuilder.addParameter("access_token", String.valueOf(map.get("access_token")));
			HttpPost httpPost = new HttpPost(uriBuilder.build());
            httpPost.addHeader("Content-type", "application/x-www-form-urlencoded;;charset=utf-8");
            List<NameValuePair> nvps = new ArrayList<NameValuePair>();
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue().toString()));
            }
            UrlEncodedFormEntity entity = new UrlEncodedFormEntity(nvps, Charset.forName("UTF-8"));
            httpPost.setEntity(entity);
            response = client.execute(httpPost);

            String result = EntityUtils.toString(response.getEntity(), "UTF-8");
            logger.info("第三方接口返回数据：" + result);
			return result;
        } catch (Exception e) {
            logger.error("HttpClient - sendPostForm 接口异常" + e.getMessage());
            e.printStackTrace();
            return null;
        } finally {
            client.getConnectionManager().closeIdleConnections(1, TimeUnit.MINUTES);
        }
    }

    /**
     * HTTP client get请求
     *
     * @param url
     * @param params
     * @return
     */
    public static String sendGet(String url, Map<String, Object> params) {
        DefaultHttpClient client = new DefaultHttpClient(poolingClientConnectionManager);
        setClientConnectionParams(client);
        HttpResponse response = null;
        try {

            URIBuilder uriBuilder = new URIBuilder(url);
            if (null != params) {
                for (Map.Entry<String, Object> entry : params.entrySet()) {
                    String mapKey = entry.getKey();
                    String mapValue = entry.getValue().toString();
                    uriBuilder.addParameter(mapKey, mapValue);
                }
            }
            HttpGet httpGet = new HttpGet(uriBuilder.build());
            response = client.execute(httpGet);
            if (response.getStatusLine().getStatusCode() != 200) {
                response.getEntity().getContent().close();
                return null;
            }
            String result = EntityUtils.toString(response.getEntity(), "UTF-8");
            logger.info("第三方接口返回数据：" + result);
			return result;
        } catch (Exception e) {
            logger.error("HttpClient - sendGet 接口异常" + e.getMessage());
            e.printStackTrace();
        } finally {
            client.getConnectionManager().closeIdleConnections(1, TimeUnit.MINUTES);
        }
        return null;
    }

    /**
     * HTTP client get请求
     *
     * @param url
     * @param jsonObject
     * @return
     */
    public static String sendGet(String url, JSONObject jsonObject) {
        DefaultHttpClient client = new DefaultHttpClient(poolingClientConnectionManager);
        setClientConnectionParams(client);
        HttpResponse response = null;
        try {

            URIBuilder uriBuilder = new URIBuilder(url);
            if (null != jsonObject) {
				for (String key : jsonObject.keySet()) {
					uriBuilder.addParameter(key, jsonObject.getString(key));
				}
            }
            HttpGet httpGet = new HttpGet(uriBuilder.build());
            response = client.execute(httpGet);
            if (response.getStatusLine().getStatusCode() != 200) {
                response.getEntity().getContent().close();
                return null;
            }
            String result = EntityUtils.toString(response.getEntity(), "UTF-8");
            logger.info("第三方接口返回数据：" + result);
			return result;
        } catch (Exception e) {
            logger.error("HttpClient - sendGet 接口异常" + e.getMessage());
            e.printStackTrace();
        } finally {
            client.getConnectionManager().closeIdleConnections(1, TimeUnit.MINUTES);
        }
        return null;
    }

    /**
     * HTTP client 上传文件
     *
     * @param url           第三方接口url
     * @param multipartFile 待上传文件
     * @param params        其他入参
     * @return
     */
    public static String upload(String url, MultipartFile multipartFile, Map<String, String> params) {
        DefaultHttpClient client = new DefaultHttpClient(poolingClientConnectionManager);
        setClientConnectionParams(client);
        String message = null;

        String fileName = null;
        String prefix = null;
        File file = null;
        try {
            HttpPost httpPost = new HttpPost(url);
            MultipartEntityBuilder repEntity = MultipartEntityBuilder.create();
            repEntity.setMode(HttpMultipartMode.RFC6532);
            if (multipartFile != null) {
                fileName = multipartFile.getOriginalFilename();
                prefix = fileName.substring(fileName.lastIndexOf("."));
                file = File.createTempFile(System.currentTimeMillis() + "", prefix);
                multipartFile.transferTo(file);
                FileBody bin = new FileBody(new File(file.getPath()), fileName, "application/octet-stream", null);
                repEntity.addPart("file", bin);
            }

            if (params != null) {//表单数据不为空，填充表单
                for (Map.Entry<String, String> entry : params.entrySet()) {
                    String mapKey = entry.getKey();
                    String mapValue = entry.getValue();
                    StringBody stringBody = new StringBody(mapValue);
                    repEntity.addPart(mapKey, stringBody);
                }
            }
            HttpEntity entity = repEntity.build();
            httpPost.setEntity(entity);
            HttpResponse response = client.execute(httpPost);

            if (response.getStatusLine().getStatusCode() != 200) {//响应异常
                logger.debug(String.format("get http response url=[%s]  with status code=%s", url, response.getStatusLine().getStatusCode()));
                response.getEntity().getContent().close();
                return "";
            }
            String result = EntityUtils.toString(response.getEntity(), "UTF-8");

            if (logger.isDebugEnabled()) {
                String str = result;
                logger.debug(String.format("get http response url=[%s]  with result=%s", url, str));
            }
            if (file.exists()) {
                file.delete();
            }

            return result;

        } catch (Exception e) {
            String printStr = String.format("error url=[%s], params=%s ",
                    url, fileName, params);
            logger.error(printStr, e);
            if (file.exists()) {
                file.delete();
            }
            return "";

        } finally {
            client.getConnectionManager().closeIdleConnections(1, TimeUnit.MINUTES);

        }
    }

    /**
     * http client 字节流下载
     *
     * @param url
     * @param params
     * @return
     */
    public static byte[] download(String url, Map<String, Object> params) {
        DefaultHttpClient client = new DefaultHttpClient(poolingClientConnectionManager);
        setClientConnectionParams(client);
        HttpResponse response = null;
        try {
            URIBuilder uriBuilder = new URIBuilder(url);
            if (null != params) {
                for (Map.Entry<String, Object> entry : params.entrySet()) {
                    String mapKey = entry.getKey();
                    String mapValue = entry.getValue().toString();
                    uriBuilder.addParameter(mapKey, mapValue);
                }
            }
            HttpGet httpGet = new HttpGet(uriBuilder.build());
            response = client.execute(httpGet);
            if (response.getStatusLine().getStatusCode() != 200) {
                response.getEntity().getContent().close();
                return null;
            }
            byte[] result = EntityUtils.toByteArray(response.getEntity());
            return result;
        } catch (Exception e) {
            logger.error("HttpClient - sendGet 接口异常" + e.getMessage());
            e.printStackTrace();
        } finally {
            client.getConnectionManager().closeIdleConnections(1, TimeUnit.MINUTES);
        }
        return null;
    }


    public static void setClientConnectionParams(DefaultHttpClient client) {
//        client.getParams().setParameter("Content-Encoding", "UTF-8");
        HttpConnectionParams.setSoTimeout(client.getParams(), 25000);
        HttpConnectionParams.setConnectionTimeout(client.getParams(), 10000);
    }

}
